import QWebChannel from './qwebchannel'
import QtWebSocketUtils from './QtWebSocketUtils'
import {
    CreateUUID,
    GetHtmlUrlQueryString,
    GetQtController, GetSessionStorage, DeleteSessionStorageByKey,
    MyWriteLog,
    SaveSessionStorage, IsFrameType, PubSubManager, IsHtmlUrlcontainString
} from './QtUtils'
import HCPlayer from './remote/hcplayer'
import WebRTCHCPlayer from './remote/hcplayer_KM'
import {FrameManager} from "./frame/FrameManager";
import {png_error2, png_error3} from "./blackimg/base64";
import ServerWebSocket, {SERVER_WS_CONNECT_SUCCESS} from "./ServerWebSocket";

//生命周期顺序
// 1.构造函数
// 2.preInit
// 3.postProjectInfo
// 4.preAddRemoteCanvas
// 5.preConnectBusWebSocket
// 6.preInitScene
// 7.postInitScene

/**
 * 外部连接的参数
 */
export class OutsideConnectOption {
    constructor() {
        this.cloudRenderID = '';                 //云渲染渲染id
        this.cloudSceneID = '';                  //云渲染场景id
        this.probe = -1;                         //是否是探针模式
        this.is_editor = false;                  //是否是编辑器模式
        this.str3DConfName = '';              //3D启动的配置文件名称
        this.strCloudConnectCallbackUrl = '';    //云渲染连接成功回调接口
        this.strCloudDisConnectCallbackUrl = ''; //云渲染断开回调接口
        this.extraParam = {};                    //额外的附带参数
    }
}

export class InParam {
    constructor() {
        this.webHost = '';
        this.webPort = 0;
        let arr = window.location.host.split(':');
        if(arr.length > 0) {
            this.webHost = arr[0];           //网页ip
        }
        if(arr.length > 1) {
            this.webPort = parseInt(arr[1]);           //网页port
        }
        this.isWebSocket = false;           //是否使用WebSocket
        this.isRemoteRender = false;            //是否远程渲染
        this.strProjectName = 'default';        //项目名称
        this.strWebChannel = 'Channel';         //WebChannel
        this.dataUrl = window.location.protocol + "//" + window.location.host;     //数据ip
        this.cmdRemoteWidth = 1920;                    //远程canvas 宽1920
        this.cmdRemoteHeight = 1080;                   //远程canvas 高1080
        this.cmdOriginIp = this.webHost;              //远程cmd host
        this.cmdOriginPort = this.webPort;                       //远程cmd port
        this.cmdWebSocketHost = this.webHost;              //远程cmd host
        this.cmdWebSocketPort = this.webPort;                       //远程cmd port
        this.webSocketPort = this.cmdWebSocketPort + 2;             //项目业务WebSocket 端口
        this.webSocketIp = this.webHost;                  //项目业务WebSocket Ip
        this.webRTCip = this.webHost;              //远程cmd host
        this.webRTCport = 3333;                       //远程cmd port
        this.remotePlayer = null;                   //播放对象
        this.isLog = true;                        //是否打印console
        this.platformType = PLATFORM_ORIGIN;      //平台
        this.clientType = CLIENT_WEB_RTC_REMOTE_RENDER;       //微客户端(1:正常客户端   2:微客户端   3:普通云渲染    4：WebRTC)
        this.isTestRemoteRender = false;       //时候测试远程渲染
        this.initResult = CODE_SUCCESS;         //初始化的结果
        this.exploreName = '';            //当前浏览器
        this.exploreVersion = '-1';             ////当前浏览器版本号
        this.wsBusinessObejct = null;         //业务的websocket
        this.toolServerUrl = '';     //工具的服务器ip
        this.toolWebUrl = '';     //工具的网页地址
        this.isShowToolWeb = false; //是否显示toolWeb
        this.clientWidth = 1920; //客户端宽
        this.clientHeight = 1080; //客户端高
        this.isShowLogin = false; //是否显示登录页
        this.frameWidth = 0; //iframe模式的话生效,宽
        this.frameHeight = 0; //iframe模式的话生效，高
        this.toolProjectName = ''; //调试的项目名称
        this.webrtcStreamIp = '';   //内网穿透ip
        this.webrtcStreamPort = 6000; //内网穿透port
        this.webrtcStreamID = 0;
        this.isNeedCallOutsideMethod = false;        //是否需要调用外部连接
        this.outsideConnectOption = new OutsideConnectOption();     //外部连接参数（this.isNeedOutsideConnectOption = false无效）
        this.isSupportControl3D = false;      //是否支持启动/关闭/重启三维系统

        this.ctl3DDaemonIp = '';      //3D系统的daemon守护器 ip
        this.ctl3DDaemonPort = 0;    //3D系统的daemon守护器 port
        this.server3DName = '';         //调用服务器api 杀掉和启动3D系统名称

        this.isServerWebsocket = false; //是否支持服务器websocket
        this.nServerWebsocketPort = this.webPort; //服务器websocket端口
        this.serverWebsocketIp = this.webHost; //服务器websocket端口
        this.isWSSingleLogin = false;   //服务器单点登录
        this.serverWebsocketObject = null;    //服务器的连接websocket

        this.isAutoScaleScreen = true;     //是否根据浏览器窗口自动缩放大小
    }
}

export const CODE_SUCCESS = 1;   //初始化成功
export const CODE_PRE_DOLOGIN = 2;   //登录前（展示登录页面）
export const CODE_START_GET_3D_STATUS = 3;   //开始获取3D运行状态
export const CODE_END_GET_3D_STATUS = 4;   //结束获取3D运行状态
export const CODE_START_GET_REMOTE_CONFIG = 5;   //开始获取云渲染配置信息
export const CODE_END_GET_REMOTE_CONFIG = 6;   //结束获取云渲染配置信息
export const CODE_ERROR_LOAD_PROJECT_CONFIG = -100;   //请求项目配置错误
export const CODE_ERROR_APP_WEBSOCKET = -101;   //连接App Websocket出错
export const CODE_ERROR_WEBRTC_CONFIG = -102;   //webrtc配置请求出错
export const CODE_ERROR_CMD_WEBSOCKET = -103;   //连接信令 Websocket出错
export const CODE_ERROR_EXPLORER_VERSION = -104;   //浏览器版本不支持
export const CODE_ERROR_SERVER_WEBSOCKET = -105;   //服务器 websocket
export const CODE_ERROR_WEBCHANNEL = -10;   //webChannel 加载出错
export const PLATFORM_VUE = 1;   //vue平台
export const PLATFORM_REACT = 2;   //react平台
export const PLATFORM_ORIGIN = 3;   //原生平台
export const CLIENT_NORMAL = 1;   //正常客户端
export const CLIENT_MICRO = 2;   //微客户端
export const CLIENT_CUSTOM_REMOTE_RENDER = 3;   //普通云渲染
export const CLIENT_WEB_RTC_REMOTE_RENDER = 4;   //WebRTC云渲染
export const PUBSUB_KEY_TOOLWEBSHOW_CHANGED = 'toolWeb_show_changed';   //tool 页面显影切换
export const PUBSUB_KEY_SERVER_WEBSOCKET = 'server_websocket';   //服务器websocket的消息
//场景移动
export const OPERATE_MOVE_UP = 'move_up'; //上移
export const OPERATE_MOVE_DOWN = 'move_down'; //下移
export const OPERATE_MOVE_LEFT = 'move_left'; //左移
export const OPERATE_MOVE_RIGHT = 'move_right'; //右移
//场景选择
export const OPERATE_ROTATE_LEFT = 'rotate_left'; //左转
export const OPERATE_ROTATE_RIGHT = 'rotate_right'; //右转
//鼠标按键
export const MOUSE_BUTTON_LEFT = 0; //左键
export const MOUSE_BUTTON_MIDDLE = 1; //中键
export const MOUSE_BUTTON_RIGHT = 2; //右键
//按键操作
export const  ACTION_MOVE_FORWARD = 0;
export const  ACTION_MOVE_BACK = 1;
export const  ACTION_MOVE_LEFT = 2;
export const  ACTION_MOVE_RIGHT = 3;
export const  ACTION_ROTATE_LEFT = 4;
export const  ACTION_ROTATE_RIGHT = 5;
export const  ACTION_APPLY_VIEWPOINT = 6;
export const  ACTION_SCENE_TIME_ADD = 7;
export const  ACTION_SCENE_TIME_SUBTRACT = 8;
export const  ACTION_BAKE_LIGHT = 9;
export const  ACTION_RENDER_CUBE_REFLECT = 10;
export const  ACTION_DEVELOP_TEST = 11;
export const  ACTION_CUSTOM_START = 12;


const WEBRTC_CONN_ID_KEY ='conn_id';		//WebRTC的连接key
const XMLNS = 'http://www.w3.org/2000/svg';

export default class QtBaseController {
  /**
   *
   * @param strProjectName      程序名称
   * @param strChannel          webChannel名称
   * @param axios               网络请求axios
   * @param fnInitCallback      初始化成功回调
   */
    constructor(strProjectName, strChannel, axios, fnInitCallback,platformType = PLATFORM_VUE) {
        this.inParam = new InParam();
        this.noHandleRectArray = [];    //不可操作三维的区域列表
        this.initSuccess = true;
        this.isInput = false;     //输入框是否在输入
        this.is3DRunning = false;     //已经获取到3D系统是否运行中
        this.nRequest3DStatusTask = -1; //请求3D运行状态的轮询任务
        this.nGetRemoteConfigTask = -1; //获取云渲染配置的轮询任务
        this.isManualLoadingPage = false; //是否手动隐藏加载动画
        this.isManualRefresh3DData = false; //是否手动调用刷新三维数据

        this.inParam.strChannel = strChannel;
        this.inParam.strProjectName = strProjectName;
        this.axios = axios;
        this.qtChannelObeject = null;
        this.fnInitCallback = fnInitCallback;
        window.qtController = this;

        this.inParam.platformType = platformType;
        this.axios = axios;
        this.aesKey = '123456708123456781234567';
        this.aesivKey = '1234567081234567';
        let isWebLog = GetHtmlUrlQueryString("isWebLog");
        if (isWebLog == '1') {
          isWebLog = true;
        } else {
          isWebLog = false;
        }
        window.isWebLog = isWebLog;
        let isTestRemoteRender = GetHtmlUrlQueryString("isTestRender");
        if (isTestRemoteRender == '1') {
          this.inParam.isTestRemoteRender = true;
        } else {
          this.inParam.isTestRemoteRender = false;
        }
        this.inParam.isLog = isWebLog;
        this.SetShowLog(isWebLog);
        let isWebsocket = GetHtmlUrlQueryString("isWebSocket");
        if (isWebsocket != 1) {
          isWebsocket = false;
        } else {
          isWebsocket = true;
        }
        this.inParam.isWebSocket = isWebsocket;
        let clientType = GetHtmlUrlQueryString("isClient");
        if(clientType == "") {
            //是客户端则不启用云渲染，否在启用云渲染
            clientType = CLIENT_WEB_RTC_REMOTE_RENDER;
        }
        this.inParam.clientType = clientType;
        if(clientType < CLIENT_MICRO) {
          this.inParam.isRemoteRender = false;
        }else {
          this.inParam.isRemoteRender = true;
        }
        let host = GetHtmlUrlQueryString("commonHost");
        if (host.endsWith('/')) {
          host = host.substr(0, host.length - 1);
        }
        if(host != '') {
          this.inParam.dataUrl = host;
        }
        let serverIp = this.inParam.dataUrl;
        serverIp = serverIp.replace('http://','');
        serverIp = serverIp.replace('https://','');
        let strList = serverIp.split(':');
        this.inParam.serverWebsocketIp = strList[0];
        let toolUrl = GetHtmlUrlQueryString("toolUrl");
        if(toolUrl != '') {
          let arr = toolUrl.split(';');
          if(arr.length > 0) {
            this.inParam.toolWebUrl = arr[0];
          }
          if(arr.length > 1) {
            this.inParam.toolServerUrl = arr[1];
          }
        }
        let clientWidth = GetHtmlUrlQueryString("width");
        if(clientWidth != '') {
          this.inParam.clientWidth = parseInt(clientWidth);
        }
        let clientHeight = GetHtmlUrlQueryString("height");
        if(clientHeight != '') {
          this.inParam.clientHeight = parseInt(clientHeight);
        }
        let isShowLogin = GetHtmlUrlQueryString("isShowLogin");
        if(isShowLogin == 1) {
          this.inParam.isShowLogin = true;
        }
        // if(this.inParam.isRemoteRender) {
        //   this.inParam.isShowLogin = true;
        // }
          {
              let str = GetHtmlUrlQueryString("cmd_ip");
              let ipArray = str.split(":");
              if(ipArray.length >= 2) {
                  let strCmdIp = ipArray[0];
                  let nPort = parseInt(ipArray[1]);
                  this.inParam.cmdOriginIp = strCmdIp;
                  this.inParam.cmdOriginPort = nPort;

                  this.inParam.cmdWebSocketHost = strCmdIp;
                  this.inParam.cmdWebSocketPort = nPort + 1;

                  this.inParam.webSocketIp = strCmdIp;
                  this.inParam.webSocketPort = nPort + 3;
              }
          }
          {
              let str = GetHtmlUrlQueryString("webrtc_ip");
              let ipArray = str.split(":");
              if(ipArray.length > 1) {
                  let strCmdIp = ipArray[0];
                  let nPort = parseInt(ipArray[1]);
                  this.inParam.webRTCip = strCmdIp;
                  this.inParam.webRTCport = nPort;

                  this.inParam.webrtcStreamIp = this.inParam.webRTCip;
                  this.inParam.webrtcStreamPort = this.inParam.webRTCport;
              }
          }
          {
              let str = GetHtmlUrlQueryString("deamon_ip");
              let ipArray = str.split(":");
              if(ipArray.length > 1) {
                  let strCmdIp = ipArray[0];
                  let nPort = parseInt(ipArray[1]);
                  this.inParam.ctl3DDaemonIp = strCmdIp;
                  this.inParam.ctl3DDaemonPort = nPort;
              }
          }
          {
            let str = GetHtmlUrlQueryString("render_id");
            if(str != '') {
              this.inParam.webrtcStreamID = parseInt(str);
            }
          }
        if(this.inParam.clientType > CLIENT_NORMAL) {
          this.inParam.isWebSocket = true;
        }
          let nRenderID = GetHtmlUrlQueryString('render_id');
          this.inParam.outsideConnectOption.cloudRenderID = nRenderID;
          let nSceneID = GetHtmlUrlQueryString('scene_id');
          this.inParam.outsideConnectOption.cloudSceneID = nSceneID;
          if(IsHtmlUrlcontainString('probe')) {
              let nProbe = GetHtmlUrlQueryString('probe');
              this.inParam.outsideConnectOption.probe = parseInt(nProbe);
          }
          let nEditor = GetHtmlUrlQueryString('is_editor');
          this.inParam.outsideConnectOption.is_editor = (nEditor=='1'?true:false);
          let str3DConfName = GetHtmlUrlQueryString('3d_conf');
          this.inParam.outsideConnectOption.str3DConfName = str3DConfName;
          let strConnectUrl = GetHtmlUrlQueryString('connect_url');
          this.inParam.outsideConnectOption.strCloudConnectCallbackUrl = strConnectUrl;



          let strDisConnectUrl = GetHtmlUrlQueryString('disconnect_url');
          this.inParam.outsideConnectOption.strCloudDisConnectCallbackUrl = strDisConnectUrl;

          let isSupport3D = GetHtmlUrlQueryString("isSupport3D");
          if(isSupport3D == '1') {
              this.inParam.isSupportControl3D = true;
          }
          if(IsHtmlUrlcontainString("app_name")) {
              this.inParam.strProjectName = GetHtmlUrlQueryString("app_name");
          }
          let isServerWebsocket = GetHtmlUrlQueryString("isServerWebsocket");
          if(isServerWebsocket == '1') {
            this.inParam.isServerWebsocket = true;
          }
          if(IsHtmlUrlcontainString("server_ws_ip")) {
            let ipArray = GetHtmlUrlQueryString("server_ws_ip").split(":");
            if(ipArray.length > 1) {
              let strCmdIp = ipArray[0];
              let nPort = parseInt(ipArray[1]);
              this.inParam.serverWebsocketIp = strCmdIp;
              this.inParam.nServerWebsocketPort = nPort;
            }
          }
          let isSingleLogin = GetHtmlUrlQueryString("isSingleLogin");
          if(isSingleLogin == '1') {
            this.inParam.isWSSingleLogin = true;
          }
          this.inParam.toolProjectName = GetHtmlUrlQueryString("project_name");
          let isAutoScaleScreen = GetHtmlUrlQueryString("isAutoScaleScreen");
          if(isAutoScaleScreen == '0') {
              this.inParam.isAutoScaleScreen = false;
          }

        this.preInit();
          if(this.inParam.isWSSingleLogin) {
            this.inParam.isServerWebsocket = true;
          }
          this._scaleScreen();
        let self = this;
        if(axios) {
          // 添加响应拦截器
          axios.interceptors.response.use(function (response) {
              // 对响应数据
              if(response.data.hasOwnProperty('encrypt') && response.data['encrypt'] == 1) {
                let data = JSON.parse(JSON.stringify(response.data));
                if(data['code'] == 0) {
                  //请求成功
                  let sIndex = 0;
                  while (true) {
                    let key = 'data' + sIndex;
                    if(sIndex == 0) {
                      key = 'data';
                    }else if(sIndex == 1) {
                      sIndex++;
                      continue;
                    }
                    sIndex++;
                    if(data.hasOwnProperty(key)) {
                      let strResponce = self._decrypt(data[key]);
                      try {
                        let returnvalue = JSON.parse(strResponce);
                        response.data[key] = returnvalue;
                      }catch (e) {
                        response.data[key] = strResponce;
                      }
                    }else {
                      break;
                    }
                  }
                }
              }
              let strMessage = '';
              strMessage += response.config.url;
              strMessage += '---result:' + response.status;
              if(response.data.hasOwnProperty('code')) {
                strMessage += ',api result:' + response.data['code'];
                strMessage += '\n';
              }
              if(response.headers.hasOwnProperty('token')) {
                strMessage += 'token:' + response.headers['token'];
                strMessage += '\n'
              }
              if(response.data.hasOwnProperty('data')) {
                strMessage += 'result data:';
                if(response.data['data']) {
                  strMessage += 'is not null';
                }else {
                  strMessage += 'is null';
                }
              }
              GetQtController().Web_LogToVs(strMessage);
              return response;
            },
            function (error) {
              // 对响应错误做点什么
              return Promise.reject(error);
            });
        }
        this._initialize_qtWebChannel(function (code,msg) {
          if(code == CODE_SUCCESS) {
            //连接服务器websocket
            GetQtController()._toLogin();
          }else {
            GetQtController()._doErrorCallback(code,msg);
          }}.bind(this)
        )
        PubSubManager.addEvent(this,'VS_AppWindowSize',(msg,data)=>{
            this.inParam.clientWidth = data[0];
            this.inParam.clientHeight = data[1];
        })
        PubSubManager.addEvent(this,'VS_SetProjectName',(msg,data) => {
          GetQtController().inParam.toolProjectName = data;
        });
        PubSubManager.addEvent(this,'VS_PreSceneLoaded',(msg,data) => {
          GetQtController().iVSPreSceneLoaded();
        });
        PubSubManager.addEvent(this,'VS_SceneLoaded',(msg,data) => {
          GetQtController().Web_ToolWebShow(false);
          GetQtController().iVSSceneLoaded();
        });
        PubSubManager.addEvent(this,'VS_ShowAppPage',(msg,data) => {
          GetQtController().Web_Loaded();
          if(!GetQtController().isManualRefresh3DData) {
            GetQtController().Web_Refesh3D();
          }
        });
        PubSubManager.addEvent(this,PUBSUB_KEY_SERVER_WEBSOCKET,(msg,data) => {
          //处理服务器Websocket发送的消息
          if(data.command == 'kickoff') {
            //需要退出,刷新页面
            location.reload();
          }
        });

      //API
      window.addEventListener("message", GetQtController()._receiveAPIMessage.bind(GetQtController()), false);
      window.addEventListener("keydown",GetQtController()._onKeyDown.bind(GetQtController()),false);
      window.addEventListener("keyup",GetQtController()._onKeyUp.bind(GetQtController()),false);
      if(GetQtController().inParam.clientType == CLIENT_WEB_RTC_REMOTE_RENDER) {
        window.addEventListener("dblclick",GetQtController()._onMouseDbClick.bind(GetQtController()),false);
      }
      window.addEventListener("resize",function () {
          this._scaleScreen();
      }.bind(GetQtController()),false);
      window.addEventListener("message", GetQtController()._receiveFrameMessage.bind(GetQtController()), false);

      console.log('InParam--', this.inParam);
    }

  /*********************************公共方法*************************************************/
  /**
   * 获取data host
   */
  GetInParam() {
    return this.inParam;
  }

  /**
   * 发送三维不可操作的区域
   * @param {*} elementClass
   */
  StartSendCoverScenePos(elementClass, intervalTime = 500) {
    this.nPosTimeID = setInterval(() => {
      let bSend = true;
      if(!IsFrameType()) {
        if(GetQtController().inParam.isShowToolWeb) {
          bSend = false;
        }
      }
      if(bSend) {
        this._doGetCoverScenePos(elementClass);
        //键盘按键是否操作三维
        this._checkKeyBoard();
      }
    }, intervalTime);
  }

  /**
   * 停止发送位置
   */
  StopSendCoverScenePos() {
    if (this.nPosTimeID != -1) {
      clearInterval(this.nPosTimeID);
    }
  }
  AddTitleMouseEvent(elementClass) {
    let elementArray = document.getElementsByClassName(elementClass);
    for (let index in elementArray) {
      if (!(elementArray[index] instanceof HTMLElement)) {
        continue;
      }
      elementArray[index].addEventListener('mousemove', function (e) {
        GetQtController().ProjectMouseMove(e);
      });

      elementArray[index].addEventListener('mousedown', function (e) {
        GetQtController().ProjectMouseDown(e);
      });

      /*备注：全局监控鼠标抬起的事件，消除鼠标移出非监控区再释放造成程序场景操作异常*/
      elementArray[index].addEventListener('mouseup', function (e) {
        GetQtController().ProjectMouseUp(e);
      });
    }
  }

  SetShowLog(isShowLog) {
    this.isShowLog = isShowLog;
  }

  /**
   * 调用Qt方法
   * @param {1} strJsonParam
   */
  ToQtCommand(strJsonParam, isShowLog = true) {
    if(!IsFrameType()) {
      if (this.inParam.wsBusinessObejct != null) {
        let bSend = true;
        if(this.inParam.clientType == CLIENT_MICRO) {
          let sendFunc = ["slotWebMouseDownApp","slotWebMouseUp","slotWebMouseMove",
            "slotAppMin","slotAppClose"];
          if(sendFunc.indexOf(strJsonParam.strFunName) != -1) {
            bSend = false;
          }
        }
        if(bSend) {
          this.inParam.wsBusinessObejct.sendAppText(JSON.stringify(strJsonParam));
        }
      } else {
        if (this.qtChannelObeject != undefined && this.qtChannelObeject != null
          && this.qtChannelObeject.slotFromWebFun != undefined) {
          this.qtChannelObeject.slotFromWebFun(strJsonParam);
        }
      }
      //当时微客户端
      if(this.qtChannelObeject != undefined && this.qtChannelObeject != null
        && this.qtChannelObeject.slotMicroFromWebFun != undefined) {
        this.qtChannelObeject.slotMicroFromWebFun(strJsonParam);
      }
    }else {
      this._postMessage(strJsonParam)
    }
    if (this.isShowLog && isShowLog) {
      MyWriteLog(strJsonParam);
    }
  }

  CreateParam(strfunname, param) {
    let strJson = {
      "strWebChannel": this.inParam.strWebChannel,
      "strFunName": strfunname,
      "Param": param,
    }
    return strJson;
  }

  /**
   * 显示/隐藏 默认加载页面
   * @param isShow
   * @constructor
   */
  ShowDefaultLoadingPage(isShow) {
    FrameManager.getInstance().setViewShow('DefaultLoading',isShow);
  }

  /**
   * 是否手动操作加载动画
   * @constructor
   */
  SetManualLoadingPage(isManual) {
    this.isManualLoadingPage = isManual;
  }

  /**
   * 给iframe发送消息
   * @param strFrameID
   * @param strCode
   * @param dataArray
   * @constructor
   */
  ToIFrameMessage(strFrameID,strCode,dataArray) {
    let iframeEle = document.getElementById(strFrameID);
    if(iframeEle) {
      let postData = {};
      postData['key'] = 'to_iframe_message';
      postData['code'] = strCode;
      postData['data'] = dataArray;
      iframeEle.contentWindow.postMessage(postData,'*');
    }
  }

  /**
   * 给父发送消息
   * @param strCode
   * @param dataArray
   * @constructor
   */
  ToParentMessage(strCode,dataArray) {
    if(window.parent) {
      let selfID = GetHtmlUrlQueryString('element_id');
      if(!selfID) {
          selfID = 'iframe';
      }
      let postData = {};
      postData['key'] = 'to_parent_message';
      postData['frameId'] = selfID;
      postData['code'] = strCode;
      postData['data'] = dataArray;
      window.parent.postMessage(postData,'*');
    }
  }
  /*********************************公共方法*************************************************/

    /*********************************类继承方法*************************************************/
    /**
     * 场景加载前
     */
    iVSPreSceneLoaded() {

    }

    /**
     * 场景加载完
     */
    iVSSceneLoaded() {

    }
    /**
     * 登录
     */
    doLogin() {
      this.startScene();
    }
    /**
     * 处理收到api的消息
     * @param messageEvent
     */
    handleAPIMessageWhenReceive(strFunc,data) {

    }
    /**
     * 开始加载scene
     */
    startScene() {
      //请求服务server websocket端口
      //显示加载页面
      if(!this.isManualLoadingPage) {
        GetQtController().ShowDefaultLoadingPage(true);
      }
      this._requestProjectConfig().then((isNext) => {
        if(isNext) {
          //连接服务器的websocket
          if(this.inParam.isServerWebsocket) {
            this.inParam.serverWebsocketObject = new ServerWebSocket(this.inParam.serverWebsocketIp,this.inParam.nServerWebsocketPort,function (connected_status) {
              if(connected_status == SERVER_WS_CONNECT_SUCCESS) {
                this._startDoScene();
              }else {
                GetQtController()._doErrorCallback(CODE_ERROR_SERVER_WEBSOCKET,'服务器websocket连接失败');
                return;
              }
            }.bind(this))
          }else {
            this._startDoScene();
          }
        }
      });
    }

    /**
     * 在Init之前
     */
    preInit() {
      if(this.inParam.isNeedCallOutsideMethod) {
        console.log('请设置外部连接参数！')
      }
    }

    /**
     * 在connect 业务WebSocket之前
     */
    preConnectBusWebSocket() {

    }

    /**
     * 初始化场景之前
     */
    preInitScene() {

    }

    /**
     * 显示app页面之前
     */
    preShowAppPage() {

    }

    /**
     * 初始化场景后
     */
    postInitScene() {

    }

    /**
     * 添加云渲染前
     */
    preAddRemoteCanvas() {

    }

    /**
     * 获取项目数据后
     */
    postProjectInfo() {

    }

    /**
     * 开始播放webrtc视频
     */
    onPlayWebRtcVideo(outsideConnectOption) {

    }

    /**
     * 初始化错位
     * @param code
     * @param msg
     */
    onInitError(code,msg) {
      if(this.inParam.initResult == code) {
        //只相应一次
        return;
      }
      this.inParam.initResult = code;
      if(code == CODE_ERROR_LOAD_PROJECT_CONFIG || code == CODE_ERROR_WEBRTC_CONFIG){
        this._addStyle();
        this._addDomOne();
      }
      if(code == CODE_ERROR_APP_WEBSOCKET || code == CODE_ERROR_CMD_WEBSOCKET){
        this._addStyle();
        this._addDomTwo();
      }
      if(code == CODE_ERROR_EXPLORER_VERSION){
        this._addStyle();
        this._addDomTwo();
      }
      DeleteSessionStorageByKey(WEBRTC_CONN_ID_KEY);
      //关闭websocket
      if(code != CODE_SUCCESS) {
        if(this.inParam.wsBusinessObejct) {
          this.inParam.wsBusinessObejct.close();
        }
        if(this.inParam.remotePlayer) {
          this.inParam.remotePlayer.close();
        }
      }
    }
    /*********************************类继承方法*************************************************/

    /*********************************To VS方法*************************************************/
    ProjectMouseMove(e) {
      let paramJson = {
        "ParamList": [
          { "param": e.x },
          { "param": e.y }]
      }
      let strJsonParam = this.CreateParam("slotWebMouseMove", paramJson);
      this.ToQtCommand(strJsonParam,false)
    }

  ProjectMouseDown(e) {
    let paramJson = {
      "ParamList": [
        { "param": e.x },
        { "param": e.y },
        { "param": e.button }]
    }
    //e.button    0:左键 1:中建 2:右键
    let strJsonParam = this.CreateParam("slotWebMouseDownApp", paramJson);
    this.ToQtCommand(strJsonParam)
  }

  ProjectMouseUp(e) {
    let paramJson = {
      "ParamList": [
        { "param": e.x },
        { "param": e.y },
        { "param": e.button }]
    }
    //e.button    0:左键 1:中建 2:右键
    let strJsonParam = this.CreateParam("slotWebMouseUp", paramJson);
    this.ToQtCommand(strJsonParam)
  }

  /**
   * 最小化
   */
  SetAppMin() {
    let strJsonParam = this.CreateParam("slotAppMin", "");
    this.ToQtCommand(strJsonParam)
  }

  /**
   * 关闭
   */
  CloseApp() {
    let strJsonParam = this.CreateParam("slotAppClose", "");
    this.ToQtCommand(strJsonParam)
  }


  //----------------------------------------------------键鼠控制-----------------------------------------------//
  MouseMove(e) {
    let paramJson = {
      "ParamList": [
        { "param": e.x },
        { "param": e.y }]
    }
    let strJsonParam = this.CreateParam("slotWebMouseMove", paramJson);
    this.ToQtCommand(strJsonParam);
  }

  MouseDown(e) {
    let paramJson = {
      "ParamList": [
        { "param": e.x },
        { "param": e.y },
        { "param": e.button }]
    }
    //e.button    0:左键 1:中建 2:右键
    let strJsonParam = this.CreateParam("slotWebMouseDown", paramJson);
    this.ToQtCommand(strJsonParam);
  }

  MouseUp(e) {
    let paramJson = {
      "ParamList": [
        { "param": e.x },
        { "param": e.y },
        { "param": e.button }]
    }
    //e.button    0:左键 1:中建 2:右键
    let strJsonParam = this.CreateParam("slotWebMouseUp", paramJson);
    this.ToQtCommand(strJsonParam);
  }

  MouseWheel(e) {
    let paramJson = {
      "ParamList": [
        { "param": e.x },
        { "param": e.y },
        { "param": e.wheelDelta }]
    }
    //e.wheelDelta    步值
    let strJsonParam = this.CreateParam("slotWebMouseWheel", paramJson);
    this.ToQtCommand(strJsonParam);
  }

  MouseDBClick(e) {
    let paramJson = {
      "ParamList": [
        { "param": e.x },
        { "param": e.y },
        { "param": e.button }]
    }
    let strJsonParam = this.CreateParam("slotWebMouseDBClick", paramJson);
    this.ToQtCommand(strJsonParam);
  }

  MouseKeyDown(e) {
    let paramJson = {
      "ParamList": [
        { "param": e.keyCode }]
    }
    let strJsonParam = this.CreateParam("slotWebKeyDown", paramJson);
    this.ToQtCommand(strJsonParam);
  }

  MouseKeyUp(e) {
    let paramJson = {
      "ParamList": [
        { "param": e.keyCode }]
    }
    let strJsonParam = this.CreateParam("slotWebKeyUp", paramJson);
    this.ToQtCommand(strJsonParam);
  }

  /**
   * 键盘按下
   * @param e   按键数组
   * @constructor
   */
  KeyBoardDown(keyArray) {
    let paramJson = {
      "ParamList": [
        { "param": keyArray }]
    }
    let strJsonParam = this.CreateParam("KeyBoardDown", paramJson);
    this.ToQtCommand(strJsonParam);
  }

  KeyBoardUp(keyArray) {
    let paramJson = {
      "ParamList": [
        { "param": keyArray }]
    }
    let strJsonParam = this.CreateParam("KeyBoardUp", paramJson);
    this.ToQtCommand(strJsonParam);
  }

  //----------------------------------------------------键鼠控制-----------------------------------------------//

  /**
   * 发送三维不可操作区域
   * @param {*} rectArray
   */
  SendCoverScenePos(rectArray) {
    let paramJson = {
      "ParamList": [
        { "param": JSON.stringify(rectArray) },
      ]
    }

    let strJsonParam = this.CreateParam("SendCoverScenePos", paramJson);
    this.ToQtCommand(strJsonParam, false);
  }

  /**
   * 发送三维键盘是否可操作
   * @param {*} rectArray
   */
  SendSceneCanKeyDown(isCanKeyDown) {
    let paramJson = {
      "ParamList": [
        { "param": isCanKeyDown },
      ]
    }

    let strJsonParam = this.CreateParam("SendSceneCanKeyDown", paramJson);
    this.ToQtCommand(strJsonParam, false);
  }

  Web_Loaded() {
    let paramJson = {};
    let strJsonParam = this.CreateParam("Web_Loaded", paramJson);
    this.ToQtCommand(strJsonParam, true);
  }

  /**
   * 刷新3D数据
   * @constructor
   */
  Web_Refesh3D() {
    let paramJson = {};
    let strJsonParam = this.CreateParam("Web_Refesh3D", paramJson);
    this.ToQtCommand(strJsonParam, true);
  }

  /**
   * 加载场景
   * @param {*}
   */
  Web_InitScene() {
    let paramJson = {
      "ParamList": [
      ]
    }

    let strJsonParam = this.CreateParam("Web_InitScene", paramJson);
    this.ToQtCommand(strJsonParam, false);
  }


  /**
   * 操作场景
   * @param strOperate
   * @param fValue
   * @constructor
   */
  Web_OperateScene(strOperate,fValue = 0) {
    let paramJson = {
      "ParamList": [
        { "param": strOperate },
        { "param": fValue }
      ]
    }
    let strJsonParam = this.CreateParam("Web_OperateScene", paramJson);
    this.ToQtCommand(strJsonParam, false);
  }

  /**
   * 是否显示调试工具元素
   */
  Web_ToolWebShow(isShow) {
    let paramJson = {
      "ParamList": [
        { "param": isShow },
      ]
    }
    let strJsonParam = this.CreateParam("Web_ToolWebShow", paramJson);
    this.ToQtCommand(strJsonParam, false);
  }

  /**
   * 日志到三维
   * @param strMessage
   * @param fValue
   * @constructor
   */
  Web_LogToVs(strMessage) {
    let paramJson = {
      "ParamList": [
        { "param": strMessage }
      ]
    }
    let strJsonParam = this.CreateParam("Web_LogToVs", paramJson);
    this.ToQtCommand(strJsonParam, false);
  }

  /**
   * 鼠标是否可以用
   * @param strMessage
   * @param fValue
   * @constructor
   */
  Web_MouseButtonEnable(mouseButton,isEnable) {
    let paramJson = {
      "ParamList": [
        { "param": mouseButton },
        { "param": isEnable }
      ]
    }
    let strJsonParam = this.CreateParam("Web_MouseButtonEnable", paramJson);
    this.ToQtCommand(strJsonParam, false);
  }

  /**
   * 鼠标是否可以用
   * @param strMessage
   * @param fValue
   * @constructor
   */
  Web_MouseButtonClickEnable(mouseButton,isEnable) {
    let paramJson = {
      "ParamList": [
        { "param": mouseButton },
        { "param": isEnable }
      ]
    }
    let strJsonParam = this.CreateParam("Web_MouseButtonClickEnable", paramJson);
    this.ToQtCommand(strJsonParam, false);
  }

  /**
   * 操作是否可用
   * @param strMessage
   * @param fValue
   * @constructor
   */
  Web_ActionEnable(actionCode,isEnable) {
    let paramJson = {
      "ParamList": [
        { "param": actionCode },
        { "param": isEnable }
      ]
    }
    let strJsonParam = this.CreateParam("Web_ActionEnable", paramJson);
    this.ToQtCommand(strJsonParam, false);
  }
  /**
   *项目组合不可点击（三维屏蔽点击事件）
   * @param isEnable
   * @constructor
   */
  Web_SetProjectMouseClickEnable(isEnable) {
    this.Web_MouseButtonClickEnable(MOUSE_BUTTON_LEFT,isEnable);
    this.Web_MouseButtonClickEnable(MOUSE_BUTTON_RIGHT,isEnable);
    this.Web_MouseButtonClickEnable(MOUSE_BUTTON_MIDDLE,isEnable);
  }

  /**
   *项目组合不可操作鼠标和按键（一般用于漫游）
   * @param isEnable
   * @constructor
   */
  Web_SetProjectMouseAndActionEnable(isEnable) {
    this.Web_MouseButtonEnable(MOUSE_BUTTON_LEFT,isEnable);
    this.Web_MouseButtonEnable(MOUSE_BUTTON_RIGHT,isEnable);
    this.Web_MouseButtonEnable(MOUSE_BUTTON_MIDDLE,isEnable);
    this.Web_ActionEnable(ACTION_MOVE_FORWARD,isEnable);
    this.Web_ActionEnable(ACTION_MOVE_BACK,isEnable);
    this.Web_ActionEnable(ACTION_MOVE_RIGHT,isEnable);
    this.Web_ActionEnable(ACTION_MOVE_LEFT,isEnable);
    this.Web_ActionEnable(ACTION_APPLY_VIEWPOINT,isEnable);
  }

    /**
     * 切换菜单
     * @param strCurMenu  当前菜单
     * @param strPreMenu  之前菜单
     * @constructor
     */
    Web_ChangeMenu(strCurMenu,strPreMenu) {
        let paramJson = {
            "ParamList": [
                { "param": strCurMenu },
                { "param": strPreMenu }
            ]
        }
        let strJsonParam = this.CreateParam("Web_ChangeMenu", paramJson);
        this.ToQtCommand(strJsonParam, false);
    }
    /*********************************To VS方法*************************************************/



    _toLogin() {
      if(this.inParam.isShowLogin) {
        this._doErrorCallback(CODE_PRE_DOLOGIN,'即将登录');
        this.doLogin();
      }else{
          if(this.inParam.isNeedCallOutsideMethod) {
              return;
          }
        this.startScene();
      }
    }

    _initialize_qtWebChannel(initializeCallback) {
      if(!this.inParam.isWebSocket) {
        //webchannel的方式
        if (typeof (window.qt) != "undefined") {
          new QWebChannel(window.qt.webChannelTransport, function (channel) {
            console.log('window.qt',channel.objects);
            if(channel.objects[GetQtController().inParam.strWebChannel] == null
              || channel.objects[GetQtController().inParam.strWebChannel] == undefined) {
              //webChannel加载失败，回调并返回
              initializeCallback(CODE_ERROR_WEBCHANNEL,'WebChannel 加载失败');
              return;
            }
            GetQtController().qtChannelObeject = channel.objects[GetQtController().inParam.strWebChannel];
            initializeCallback(CODE_SUCCESS,'WebChannel 成功');
          });
        }else {
          initializeCallback(CODE_SUCCESS,'WebChannel 不需要加载');
        }
      }else {
        initializeCallback(CODE_SUCCESS,'WebChannel 不需要加载');
      }
    }

    _initialize_loadConfig(initializeCallback) {
      if(!IsFrameType()) {
        this._toLoadConfig(initializeCallback);
      }else {
        initializeCallback(CODE_SUCCESS,'iframe模式初始化成功');
      }
    }

    _initialize_connect(initializeCallback) {
      //2.连接业务的通信方式
      //连接业务websocket方式
      if(this.inParam.isWebSocket) {
        this.preConnectBusWebSocket();
        this.inParam.wsBusinessObejct = new QtWebSocketUtils(this.inParam.webSocketIp, this.inParam.webSocketPort, (isConnected, errMsg) => {
          //加载场景
          if (isConnected) {
            initializeCallback(CODE_SUCCESS,'业务websocket连接成功');
            // setTimeout(function () {
            //   GetQtController().inParam.wsBusinessObejct = new QtWebSocketUtils(GetQtController().inParam.webSocketIp, GetQtController().inParam.webSocketPort, null);
            // }, 10000);
          } else {
            //连接失败
            initializeCallback(CODE_ERROR_APP_WEBSOCKET, 'App 业务WebSocket 连接失败');
          }
        });
        this.inParam.wsBusinessObejct.setReConnectedCallback(this._wsReConnectedCallback);
      }else {
        initializeCallback(CODE_SUCCESS, '无需连接websock');
      }
    }

    /**
     * 初始化
     * @param initializeCallback
     */
    _initialize(initializeCallback) {
      //1.处理获取配置
      this._initialize_loadConfig(function (code,msg) {
        if(code == CODE_SUCCESS) {
          //2.连接业务的通信方式
          GetQtController()._initialize_connect(function (code,msg) {
            if(code == CODE_SUCCESS) {
              //3.添加监听
              let isAddListener = false;
              if(IsFrameType()) {
                isAddListener = true;
              }else if(GetQtController().inParam.toolWebUrl != '') {
                isAddListener = true;
              }
              if(isAddListener) {
                window.addEventListener("message", GetQtController()._receiveMessage.bind(GetQtController()), false);
              }
              initializeCallback(code,msg);
            }else {
              initializeCallback(code,msg);
            }
          });
        }else {
          initializeCallback(code,msg);
        }
      })
    }

  /**
   * 键盘按下
   * @param keyEvent
   * @private
   */
    _onKeyDown(keyEvent) {
      //判断是否启用toolLabel
      //alt+T
      if(keyEvent.keyCode == 84 && keyEvent.altKey) {
        if(GetQtController().inParam.toolWebUrl != '') {
          GetQtController().inParam.isShowToolWeb = !GetQtController().inParam.isShowToolWeb;
          FrameManager.getInstance().sendPubSubMessage(PUBSUB_KEY_TOOLWEBSHOW_CHANGED,GetQtController().inParam.isShowToolWeb);
        }
        if(IsFrameType()) {
          //像上级发送
          let postData = {};
          postData['key'] = 'keydown';
          postData['data'] = 'alt+t';
          window.parent.postMessage(postData,'*');
        }
      }
      //不是输入框输入
      if(!GetQtController().isInput) {
        GetQtController().MouseKeyDown(keyEvent);
      }
    }

    /**
     * 键盘松开
     * @param keyEvent
     * @private
     */
    _onKeyUp(keyEvent) {
      //不是输入框输入
      if(!GetQtController().isInput) {
        GetQtController().MouseKeyUp(keyEvent);
      }
    }

    /**
     * 双击
     * @param keyEvent
     * @private
     */
    _onMouseDbClick(keyEvent) {
      //不是输入框输入
      GetQtController().MouseDBClick(keyEvent);
    }

    /**
     * 接收message
     * @param messageEvent
     * @private
     */
    _receiveMessage(messageEvent) {
      if(messageEvent && messageEvent.data != undefined) {
        if(messageEvent.data.key == 'ToIFrameQtMessage') {
          //处理父页面传递过来的Qt事件
          let strCode = messageEvent.data.code;
          let data = messageEvent.data.data;
          FrameManager.getInstance().sendPubSubMessage(strCode,data);
        }else if(messageEvent.data.key == 'keydown') {
          if(messageEvent.data.data == 'alt+t') {
            GetQtController().inParam.isShowToolWeb = !GetQtController().inParam.isShowToolWeb;
            FrameManager.getInstance().sendPubSubMessage(PUBSUB_KEY_TOOLWEBSHOW_CHANGED,GetQtController().inParam.isShowToolWeb);
          }
        }
      }
    }

    _receiveFrameMessage(messageEvent) {
      if(messageEvent && messageEvent.data != undefined
          && (messageEvent.data.key == 'to_iframe_message' || messageEvent.data.key == 'to_parent_message')) {
        let strFrameID = messageEvent.data.frameId;
        if(!strFrameID){
          strFrameID = 'parent';
        }
        let strCode = messageEvent.data.code;
        let data = [];
        data["frameID"] = strFrameID;
        data["code"] = strCode;
        data["data"] = messageEvent.data.data;
        FrameManager.getInstance().sendPubSubMessage("key_frame_message",data);
      }
    }

  /**
   * 接收api message
   * @param messageEvent
   * @private
   */
  _receiveAPIMessage(messageEvent) {
    if (messageEvent && messageEvent.data.key == 'to_hc_message') {
      //处理API 外部传递的消息
      let strCode = messageEvent.data.code;
      let data = messageEvent.data.data;

      let strJsonData = GetQtController()._createParamFromAPI(strCode, data);
      GetQtController().ToQtCommand(strJsonData);

      //恢复
        {
            let hcData = {};
            hcData.key = 'response_command';
            hcData.code = strCode;
            hcData.data = data;
            window.parent.postMessage(hcData,'*');
        }

        console.log(strCode,GetQtController().inParam.frameWidth,GetQtController().inParam.frameHeight);
        if(strCode == 'frameSize') {
            this.inParam.frameWidth = data[0];
            this.inParam.frameHeight = data[1];
        }
        this.handleAPIMessageWhenReceive(strCode,data);
    }
  }

    /**
     * 向父发送postMessage
     * @param strCode
     * @param data
     * @private
     */
    _postMessage(data) {
      let postData = {};
      postData['key'] = 'iframeMessage';
      postData['data'] = data;
      window.parent.postMessage(postData,'*');
    }


  /**
   * 获取渲染服务器的地址
   */
  _requestRenderService() {
      let p = new Promise((resolve, reject) => {
        if(this.inParam.cmdOriginIp != '' && this.inParam.isTestRemoteRender) {
            this._do3DCheck(()=>{
                //检测好3D运行状态后
                resolve(true);
            })
          return;
        }
        this._doGetRemoteConfig((isNext)=>{
          resolve(isNext);
        });
      })
      return p;
  }

  /**
   * 获取项目配置
   */
  _requestProjectConfig() {
    let p = new Promise((resolve, reject) => {
      if(this.inParam.clientType < CLIENT_CUSTOM_REMOTE_RENDER || this.inParam.isTestRemoteRender) {
        //不是云渲染或者是测试云渲染的
        resolve(true);
        return;
      }

      let host = this.inParam.dataUrl;
      let url = `${host}/admin/project/getconfig?project_name=${this.inParam.strProjectName}`
      this.axios.get(url).then(res => {
        let resultData = res.data;
        if (resultData == null || resultData == undefined) {
          let strMsg = "请求项目配置出错!";
          this.initSuccess = false;
          this._doErrorCallback(CODE_ERROR_LOAD_PROJECT_CONFIG, strMsg);

          resolve(false);
          return;

        }
        // let remote_render = resultData.data.remote_render;
        // let remoteType = remote_render.split(',');
        // if (remoteType.length > 0) {
        //   let nType = remoteType[0];
        //   if (nType == 1) {
        //     this.inParam.clientType = CLIENT_CUSTOM_REMOTE_RENDER;
        //   } else if (nType == 2) {
        //     //WebRTC
        //     this.inParam.clientType = CLIENT_WEB_RTC_REMOTE_RENDER;
        //   }
        // }

        if(!resultData.data.cloud_render) {
          resolve(true);
          return;
        }
        //解析服务器websocket数据
        let cloudRenderObject = JSON.parse(resultData.data.cloud_render);
        let singleLoginObject = JSON.parse(resultData.data.single_login);
        if(singleLoginObject && singleLoginObject.hasOwnProperty('enable')) {
          this.inParam.isWSSingleLogin = (singleLoginObject['enable'] == 1);
          if(this.inParam.isWSSingleLogin) {
            this.inParam.isServerWebsocket = true;
          }
        }
        if(singleLoginObject && singleLoginObject.hasOwnProperty('port')) {
          this.inParam.nServerWebsocketPort = singleLoginObject['port'];
        }
        if(cloudRenderObject && cloudRenderObject.hasOwnProperty('mode')) {
          //mode=1,代表昆明模式，2代表多用户动态切换模式
          this.inParam.isSupportControl3D = (cloudRenderObject['mode'] == 2);
        }
        resolve(true);
        return;
      }).catch(err => {
        let strMsg = "请求项目配置出错!";
        let errData = err.data;
        this.initSuccess = false;
        this._doErrorCallback(CODE_ERROR_LOAD_PROJECT_CONFIG, strMsg);

        resolve(false);
        return;
      })
    })
    return p;
  }

  /**
   * 获取webrtc地址
   */
  _requestWebRTCConfig() {
    let p = new Promise((resolve, reject) => {
      if(this.inParam.webRTCip != '' && this.inParam.isTestRemoteRender) {
        resolve(true);
        return;
      }

      let host = this.inParam.dataUrl;
      let url = `${host}/admin/project/getrtchost`
      this.axios.get(url).then(res => {
        let resultData = res.data;
        if (resultData == null || resultData == undefined) {
          let strMsg = "请求WebRTC配置出错!";
          this.initSuccess = false;
          this._doErrorCallback(CODE_ERROR_WEBRTC_CONFIG, strMsg);

          resolve(false);
          return;
        }
        let strIp = resultData.data;
        let ips = strIp.split(':');
        if (ips.length > 0) {
          this.inParam.webRTCip = ips[0];
        }
        if (ips.length > 1) {
          this.inParam.webRTCport = parseInt(ips[1]);
        }

        resolve(true);
      }).catch(err => {
        let strMsg = "请求项目配置出错!";
        let errData = err.data;
        this.initSuccess = false;
        this._doErrorCallback(CODE_ERROR_LOAD_PROJECT_CONFIG, strMsg);

        resolve(false);
      })
    })
    return p;
  }

    /**
     * 控制3D系统,start,stop,restart
     * fnCallback回调 (strCommond,resultCode)=>{}
     * @private
     */
  _requestControl3D(strCommond,fnCallback) {
      let host = window.location.protocol + "//" + this.inParam.ctl3DDaemonIp + ':' + this.inParam.ctl3DDaemonPort;
      let url = `${host}/api/daemon/operateApp?appName=${this.inParam.server3DName}&action=${strCommond}&params=${this.inParam.outsideConnectOption.str3DConfName}`;
      this.axios.get(url).then(res => {
          console.log(`api/daemon/operateApp?appName=${this.inParam.server3DName}&action=${strCommond},result=`,res.data.code);
          let resultCode = res.data.code;
          if(resultCode == -1 && strCommond == 'stop') {
            //停止失败
            resultCode = 0;
          }
          if(fnCallback) {
            fnCallback(strCommond,resultCode);
          }
      })
  }

    /**
     * 处理3D系统
     * @private
     */
  _do3DCheck(fn3DStatusCallback) {
        if(!this.inParam.isSupportControl3D) {
            if(fn3DStatusCallback) {
                fn3DStatusCallback();
            }
            return;
        }
        if(!this.inParam.ctl3DDaemonIp) {
            console.log('3D控制端，ip为空，请处理====================');
        }
        this._doErrorCallback(CODE_START_GET_3D_STATUS,'开始获取3D系统运行状态');
        //先杀掉3D系统
        this._requestControl3D('stop',(strCommond,resultCode)=>{
            if(strCommond == 'stop' && resultCode == 0) {
                //已经杀掉3D系统,然后启动
                this._requestControl3D('start',(strCommond,resultCode)=>{
                    if(strCommond == 'start' && resultCode == 0) {
                        //已经启动
                        this._check3DStatus(fn3DStatusCallback);
                    }
                })
            }
        })
  }

    /**
     * 获取3D系统运行状态
     * fn3DStatusCallback 回调()=>{}
     * @private
     */
    _check3DStatus(fn3DStatusCallback) {
        this.nRequest3DStatusTask = setInterval(()=>{
            let host = window.location.protocol + "//" + this.inParam.ctl3DDaemonIp + ':' + this.inParam.ctl3DDaemonPort;
            let url = `${host}/api/daemon/status?appName=${this.inParam.server3DName}`;
            this.axios.get(url).then(res => {
                let nStatus = res.data.data.running;
                this.is3DRunning = (nStatus==1);
                if(this.is3DRunning) {
                    clearInterval(this.nRequest3DStatusTask);
                    this._doErrorCallback(CODE_END_GET_3D_STATUS,'结束获取3D系统运行状态');
                    if(fn3DStatusCallback) {
                        fn3DStatusCallback();
                    }
                }
            })
        },1000)
  }

  /**
   * 处理获取云渲染配置
   * fnGetRemoteConfigCallback (bool)=>{}
   * @private
   */
  _doGetRemoteConfig(fnGetRemoteConfigCallback) {
    this._doErrorCallback(CODE_START_GET_REMOTE_CONFIG,'开始获取云渲染配置信息');
    if(this.inParam.isSingleLogin) {
      //先探针
      this.nGetRemoteConfigTask = setInterval(()=>{
        this._checkRemoteConfig(1,(isStop)=>{
          if(isStop) {
            //继续轮询
            clearInterval(this.nGetRemoteConfigTask);
            this._checkRemoteConfig(0,(isStop)=>{
              //真实的
              fnGetRemoteConfigCallback(isStop);
            })
          }
        })
      },1000);
    }else {
      this._checkRemoteConfig(0,(isStop)=>{
        //真实的
        fnGetRemoteConfigCallback(isStop);
      })
    }
  }

  /**
   * 处理获取云渲染配置
   * fnRemoteConfigCallback 回调(bool)=>{}
   * @private
   */
  _checkRemoteConfig(probe,fnRemoteConfigCallback) {
    let conn_id = GetSessionStorage(WEBRTC_CONN_ID_KEY);
    if (conn_id == undefined || conn_id == null || conn_id == '') {
      conn_id = CreateUUID();
    }
    let concat_conn_id = conn_id + '_' + this.inParam.strProjectName;
    console.log('WebRTC_conn_id--', concat_conn_id)
    let host = this.inParam.dataUrl;
    let url = `${host}/admin/render_service/gethost?name=${this.inParam.strProjectName}`;
    url += `&conn_id=${concat_conn_id}`;
    url += `&render_id=${this.inParam.outsideConnectOption.cloudRenderID}`;
    url += `&scene_id=${this.inParam.outsideConnectOption.cloudSceneID}`;
    url += `&probe=${probe}`;
    url += `&is_editor=`;
    url += this.inParam.outsideConnectOption.is_editor?'1':'0';
    this.axios.get(url).then(res => {
      let resultData = res.data;
      if(probe == 1) {
        //探针模式
        if (resultData == null || resultData == undefined) {
          fnRemoteConfigCallback(false);
        }else {
          if(resultData.code == 0) {
            fnRemoteConfigCallback(true);
          }else {
            fnRemoteConfigCallback(false);
          }
        }
        return;
      }
      if (resultData == null || resultData == undefined) {
        let strMsg = "请求空闲服务器时出错!";
        this.initSuccess = false;
        this._doErrorCallback(CODE_ERROR_LOAD_PROJECT_CONFIG, strMsg);

        fnRemoteConfigCallback(false);
        return;
      }
      if (resultData.code == 0) {
        //保存token
        SaveSessionStorage(WEBRTC_CONN_ID_KEY, conn_id);

        let jssonData = resultData.data;
        this.inParam.cmdOriginIp = jssonData.render_ip;
        this.inParam.cmdOriginPort = jssonData.comm_port;

        //成功
        this.inParam.cmdWebSocketPort = jssonData.comm_port + 1;
        this.inParam.cmdWebSocketHost = jssonData.render_ip;
        this.inParam.webSocketPort = jssonData.comm_port + 3;
        this.inParam.webSocketIp = jssonData.render_ip;

        let ipArray = jssonData.rtc_host.split(":");
        if(ipArray.length > 1) {
          let strCmdIp = ipArray[0];
          let nPort = parseInt(ipArray[1]);
          this.inParam.webRTCip = strCmdIp;
          this.inParam.webRTCport = nPort;
        }

        this.inParam.webrtcStreamID =jssonData.id;
        this.inParam.outsideConnectOption.cloudRenderID = this.inParam.webrtcStreamID;

        if(jssonData.hasOwnProperty('nat_ip')) {
          this.inParam.webrtcStreamIp = jssonData.nat_ip;
          this.inParam.webrtcStreamPort = this.inParam.cmdOriginPort;

          this.inParam.ctl3DDaemonIp = jssonData.nat_ip;
        }
        if(jssonData.hasOwnProperty('control_port')) {
          this.inParam.ctl3DDaemonPort = jssonData.control_port;
        }
        if(jssonData.hasOwnProperty('param')) {
          this.inParam.outsideConnectOption.str3DConfName = jssonData.param;
        }
        if(jssonData.hasOwnProperty('service_name')) {
          this.inParam.server3DName = jssonData.service_name;
        }

        this._do3DCheck(()=>{
          //检测好3D运行状态后
          fnRemoteConfigCallback(true);
        })
      } else {
        this.initSuccess = false;
        let strMsg = "没有空闲的服务器，请耐心等待（或联系管理员处理）!";
        this._doErrorCallback(CODE_ERROR_LOAD_PROJECT_CONFIG, strMsg);

        fnRemoteConfigCallback(false);
      }
    }).catch(err => {
      let strMsg = "请求空闲服务器时出错!";
      let errData = err.data;
      this.initSuccess = false;
      this._doErrorCallback(CODE_ERROR_LOAD_PROJECT_CONFIG, strMsg);

      fnRemoteConfigCallback(false);
    })
  }

  /**
   * 检测浏览器版本
   */
  _checkExploreSupport() {
    let p = new Promise((resolve, reject) => {
      //判断浏览器及版本
      /*this._isGoodleChrome()
      if (this.inParam.exploreName != "Chrome" || this.inParam.exploreVersion < "87") {
        this.initSuccess = false;
        this._doErrorCallback(CODE_ERROR_EXPLORER_VERSION, '浏览器版本不支持！');
        alert('请使用chrome浏览器或者版本大于等于87版本');

        resolve(false);
        return;
      }*/
      resolve(true);
    });
    return p;
  }

  /**
   * 获取配置信息
   * @private
   */
  _toLoadConfig(initializeCallback) {
    if (this.inParam.isRemoteRender) {
      this._requestRenderService().then((isNext) => {
        if(isNext) {
          if(this.inParam.isTestRemoteRender || this.inParam.clientType <= CLIENT_MICRO) {
            return true;
          }
          //return this._requestRenderService();
          return true;
        }
        return false;
      }).then((isNext) => {
        if(isNext) {
          if(this.inParam.isTestRemoteRender || this.inParam.clientType != CLIENT_WEB_RTC_REMOTE_RENDER) {
            return true;
          }
          return this._checkExploreSupport();
        }
        return false;
      }).then((isNext) => {
        if(isNext){
          if(this.inParam.clientType == CLIENT_WEB_RTC_REMOTE_RENDER) {
            //return this._requestWebRTCConfig();
            return true;
          }
          return true;
        }
        return false;
      }).then((isNext) => {
        if(isNext) {
          this.postProjectInfo();
          initializeCallback(CODE_SUCCESS,"toLoadConfig 获取配置成功!");
        }else {
          initializeCallback(CODE_ERROR_LOAD_PROJECT_CONFIG,"toLoadConfig 获取配置失败!");
        }
        console.log('InParam--', this.inParam);
      })
    }else {
      this.postProjectInfo();
      initializeCallback(CODE_SUCCESS,"无需获取配置，成功");
      console.log('InParam--', this.inParam);
    }
  }

    /**
     * 场景已加载完成
     * @private
     */
    _sceneComplete() {
      this._postSceneLoaded();
      this.postInitScene();
    }

    _postSceneLoaded() {
      let that = this;
      this._postInitScene();
      setTimeout(function () {
        let desktopArray = document.getElementById('app');
        if(desktopArray && GetQtController().GetInParam().remotePlayer) {
          GetQtController().GetInParam().remotePlayer.setupMouse(desktopArray);
        };
        if(GetQtController().GetInParam().clientType <= CLIENT_MICRO) {
          //客户端
          GetQtController().AddTitleMouseEvent('project_title');
        }
      },5000)
    }

    //初始化场景之后
    _postInitScene() {
      GetQtController().StartSendCoverScenePos('3D_ignore');
      //告知项目配置信息
      let paramJson = {
        "ParamList": [
          { "param": this.inParam.cmdWebSocketHost },
          { "param": this.inParam.cmdWebSocketPort + 1 },
          { "param": this.inParam.cmdRemoteWidth },
          { "param": this.inParam.cmdRemoteHeight }
        ]
      };
      let strJsonParam = this.CreateParam("slotPostProjectInfo", paramJson);
      this.ToQtCommand(strJsonParam);
    }

    _wsReConnectedCallback() {
        //WebSocket重连成功回调
        GetQtController().Web_Loaded();
    }

    //添加canvas播放远程渲染画面
    _addRemoteCanvas() {
        let canvas = null;
        if(this.inParam.clientType == CLIENT_WEB_RTC_REMOTE_RENDER) {
          canvas = document.createElement('video');
          canvas.autoplay = true;
          canvas.muted = true;
          canvas.addEventListener('canplaythrough', function(e) {
              this.onPlayWebRtcVideo(this.inParam.outsideConnectOption);
          }.bind(this))
        }else if(this.inParam.clientType == CLIENT_CUSTOM_REMOTE_RENDER
          || this.inParam.clientType == CLIENT_MICRO){
          canvas = document.createElement('canvas');
        }
        if(!canvas) {
          return;
        }
        let renderWidth = this.inParam.cmdRemoteWidth;
        let renderHeight = this.inParam.cmdRemoteHeight;
        let remote_port = this.inParam.cmdWebSocketPort;
        let remote_ip = this.inParam.cmdWebSocketHost;

        let rtc_ip = this.inParam.webRTCip;
        let rtc_port = this.inParam.webRTCport;
        let webrtc_stream_id = this.inParam.webrtcStreamID;
        let webrtc_stream_ip = this.inParam.webrtcStreamIp;
        let webrtc_stream_port = this.inParam.webrtcStreamPort;

        canvas.id = 'remote_video';
        canvas.style.width = renderWidth;
        canvas.style.height = renderHeight;
        document.body.appendChild(canvas);

        let workerPath = null;
        if(this.inParam.platformType == PLATFORM_VUE) {
          workerPath= "resource/remoteRender/remote/";
        }else if(this.inParam.platformType == PLATFORM_REACT) {
          workerPath= "remoteRender/remote/";
        }else if(this.inParam.platformType == PLATFORM_ORIGIN) {
          workerPath= "qtWebBridge/static/remoteRender/remote/";
        }

        console.log('workerPath--' + workerPath);
        let playerParam = {};
        let isHcPlayerNative = false;
        if(this.inParam.clientType <= CLIENT_MICRO) {
          isHcPlayerNative = true;
        }
        if(workerPath != null) {
          if(this.inParam.clientType == CLIENT_WEB_RTC_REMOTE_RENDER) {
            this.inParam.remotePlayer = new WebRTCHCPlayer();
            let rtcInitParam = {ip:rtc_ip,port:rtc_port,width:renderWidth,height:renderHeight,videoWnd:canvas};
            playerParam = {ip:remote_ip,port:remote_port,width:renderWidth,height:renderHeight,login:"login",pass:"pass",
              workerPath:workerPath,canvas:null,bSetupMouse:false,supportRtc:true,isNative:isHcPlayerNative,
              rtcInitParam:rtcInitParam,streamID:webrtc_stream_id,streamIp:webrtc_stream_ip,streamPort:webrtc_stream_port};
          }else if(this.inParam.clientType == CLIENT_CUSTOM_REMOTE_RENDER
            || this.inParam.clientType == CLIENT_MICRO){
            this.inParam.remotePlayer = new HCPlayer();
            playerParam = {ip:remote_ip,port:remote_port,width:renderWidth,height:renderHeight,login:"login",pass:"pass",
              workerPath:workerPath,canvas:canvas,bSetupMouse:false,isNative:isHcPlayerNative};
          }
          playerParam.outsideConnectOption = this.inParam.outsideConnectOption;
          console.log('playerParam--',playerParam);
          this.inParam.remotePlayer.SetMousePosCallback(this._fnRemoteMouseCallback);
          this.inParam.remotePlayer.SetWebSocketCallback((code,msg)=>{
            this.onInitError(code,msg)
          });
          this.inParam.remotePlayer.init(playerParam);
        }

        document.oncontextmenu = function () {
          return false;
        }
    }

  /**
   * 执行错误回调
   * @param code
   * @param msg
   * @private
   */
    _doErrorCallback(code,msg) {
      if(this.fnInitCallback && this.fnInitCallback != undefined) {
        this.fnInitCallback(code,msg);
      }

      if(!this.isManualLoadingPage) {
        if(code == CODE_START_GET_REMOTE_CONFIG){
          GetQtController().ShowDefaultLoadingPage(true);
        }else if(code == CODE_END_GET_REMOTE_CONFIG){
          GetQtController().ShowDefaultLoadingPage(false);
        }else if(code == CODE_START_GET_3D_STATUS){
          GetQtController().ShowDefaultLoadingPage(true);
        }else if(code == CODE_END_GET_3D_STATUS){
          GetQtController().ShowDefaultLoadingPage(false);
        }
      }

      this.onInitError(code,msg);
    }

    // 判断浏览器及版本
    _isGoodleChrome(){
      //取得浏览器的userAgent字符串
      var userAgent = navigator.userAgent;
      var isOpera = userAgent.indexOf("Opera") > -1;

      let browser = [];
      //谷歌
      if (userAgent.match(/Chrome\/([\d.]+)/)){
        let strStart = userAgent.indexOf('Chrome')
        let strStop = userAgent.indexOf('Safari')
        let strMiddle = userAgent.indexOf('Edg')
        let version = userAgent.substring(strStart,strStop)
        let VersionNumber = version.split('/')
        browser = ["Chrome",VersionNumber[1]]
      };

      //火狐
      if (userAgent.indexOf("Firefox") > -1) {
        let version = window.navigator.userAgent.split("/")
        let VersionNumber = version[3].split(" ")
        browser = ["Firefox",VersionNumber[0]]
      };
       // 360极速模式可以区分360安全浏览器和360极速浏览器
      // if (userAgent.indexOf('WOW') != -1 && userAgent.indexOf('NET') < 0 && userAgent.indexOf('Firefox') < 0) {
      //   if (navigator.javaEnabled()) {
      //     browser = ["360安全浏览器",-1]
      //   } else {
      //     browser = ["360极速浏览器",-1]
      //   }
      // }
      // // 360兼容
      // if (userAgent.indexOf('WOW') != -1 && userAgent.indexOf('NET') != -1 && userAgent.indexOf('MSIE') != -1 && userAgent.indexOf('rv') < 0) {
      //     browser = ["360兼容模式",-1]
      // }

      // Edge
      if (userAgent.match(/Edg.([\d.]+)/)){
        let strStart = userAgent.indexOf('Chrome')
        let strMiddle = userAgent.indexOf('Safari')
        let strStop = userAgent.indexOf('Edg')
        let version = userAgent.substring(strStop,strStart)
        let VersionNumber = version.split('/')
        browser = ["Edge",VersionNumber[1]]
      }

      //ie
      if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera) {
        let version = window.navigator.userAgent.split("/")
        let VersionNumber = version[3].split(" ")
        browser = ["IE",VersionNumber[0]]
      };

      //Opera
      if (userAgent.match(/Opera.([\d.]+)/)) {
        let strStop = userAgent.indexOf('Opera')
        let version = userAgent.substring(strStop)
        let VersionNumber = version.split('/')
        browser = ["Opera",VersionNumber[1]]
      };

      //Safari
      if (userAgent.match(/Version\/([\d.]+).*Safari/)) {
        let strStop = userAgent.indexOf('Safari')
        let version = userAgent.substring(strStop)
        let VersionNumber = version.split('/')
        browser = ["Safari",VersionNumber[1]]
      };

      if(browser.length >= 2) {
        this.inParam.exploreName = browser[0];
        this.inParam.exploreVersion = browser[1];
      }
    }

    _doGetCoverScenePos(elementClass) {
        this.noHandleRectArray = [];
        this._getCoverScenePos(elementClass, this.noHandleRectArray);

        this.SendCoverScenePos(this.noHandleRectArray);
    }

    //云渲染鼠标的回调，return true可操作三维，false不可操作三维
    _fnRemoteMouseCallback(x,y) {
      let isCanMouse = true;
      let that = GetQtController();
      for(let i in that.noHandleRectArray) {
        let rect = that.noHandleRectArray[i];
        if(x >= rect.left && x <= rect.right
          && y >= rect.top && y <= rect.bottom) {
          isCanMouse = false;
          break;
        }
      }
      return isCanMouse;
    }


    _getCoverScenePos(elementClass, posArray) {
        let elementArray = document.getElementsByClassName(elementClass);
        for (let i in elementArray) {
            if (!(elementArray[i] instanceof HTMLElement)) {
                continue;
            }
            if (elementArray[i].style.display == "none" || elementArray[i].style.backgroundColor == "transparent" || elementArray[i].style.background == "transparent") {
                continue;
            }
            let top = elementArray[i].getBoundingClientRect().top + window.scrollY;
            let left = elementArray[i].getBoundingClientRect().left;
            let right = left + elementArray[i].clientWidth;
            let bottom = top + elementArray[i].clientHeight;
            posArray.push({ left: parseInt(left), top: parseInt(top), right: parseInt(right), bottom: parseInt(bottom) });
        }
    }

  /**
   * 判断键盘是否是输入框在输入
   * @private
   */
  _checkKeyBoard() {
      let isFocus = false;
      if(document.activeElement && (document.activeElement.tagName.toLowerCase() == 'input'
        || document.activeElement.tagName.toLowerCase() == 'textarea')) {
        isFocus = true;
      }
      GetQtController().isInput = isFocus;
      GetQtController().SendSceneCanKeyDown(!GetQtController().isInput);
    }

  /**
   *创建API传递给Qt的数据
   * @param strFuncName
   * @param dataArray
   * @returns {*}
   * @private
   */
    _createParamFromAPI(strFuncName,dataArray) {
      let paramJson = {
        "ParamList": [
        ]
      };
      for(let i in dataArray) {
        let jsonParam = {};
        jsonParam.param = dataArray[i];
        paramJson.ParamList.push(jsonParam);
      }
      let strJsonData = this.CreateParam(strFuncName,paramJson);
      return strJsonData;
    }

  /**
   * 解密
   * @param data
   * @returns {string}
   */
    _decrypt(data){   //aes decrypt
      let key = CryptoJS.enc.Utf8.parse(this.aesKey);
      let ivKey = CryptoJS.enc.Utf8.parse(this.aesivKey);

      let options = {
        iv:ivKey,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
      };

      let decryptedData = CryptoJS.AES.decrypt(data, key, options);
      let decryptedStr = decryptedData.toString(CryptoJS.enc.Utf8);

      return decryptedStr;
    }

  /**
   * 加密
   * @param data
   * @returns {string}
   */
    _encrypt(data){
      let key = CryptoJS.enc.Utf8.parse(this.aesKey);
      let ivKey = CryptoJS.enc.Utf8.parse(this.aesivKey);

      let options = {
        iv:ivKey,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
      };
      let encrypted = CryptoJS.AES.encrypt(data, key, options);

      // ciphertext是密文，toString()内传编码格式，比如Base64，这里用了16进制
      return  encrypted.ciphertext.toString(CryptoJS.enc.Utf8);
    }

    /**
     * 初始化失败
     */
    _createStyle(){
        return"*{padding:0;margin:0;border:0}.loading{width:100%;height:100%;position: fixed;left:0px;top:0px;}.loadImg{width:1920px;height:1080px;}"
    }
    _addStyle(){
        let style = document.createElement("style");
        style.type = "text/css";
        style.innerHTML = this._createStyle();
        window.document.head.appendChild(style);
    }
    _addDomOne(){
        let div = document.createElement("div");
        div.className = "loading";
        window.document.body.appendChild(div);
        let img = document.createElement("img");
        img.src=png_error2;
        img.id="loadImg";
        img.className="loadImg";
        div.appendChild(img);
    }
    _addDomTwo(){
      let div = document.createElement("div");
      div.className = "loading";
      window.document.body.appendChild(div);
      let img = document.createElement("img");
      img.src=png_error3;
      img.id="loadImg";
      img.className="loadImg";
      div.appendChild(img);
    }

    /**
     * 开始加载场景
     * @private
     */
    _startDoScene() {
      this.preInitScene();
      this._initialize(function (code,msg) {
        if(!this.isManualLoadingPage) {
          GetQtController().ShowDefaultLoadingPage(false);
        }
        if(code == CODE_SUCCESS) {
          GetQtController().Web_LogToVs('Web startScene--初始化码：' + code);
          GetQtController().Web_LogToVs('inParam:' + JSON.stringify(this.inParam));

          this._doErrorCallback(code,'初始化完成');
          //显示app页面
          // if(!this.qtChannelObeject) {
          //   VS_ShowAppPage();
          // }
          this.preShowAppPage();
          if(this.inParam.clientType == CLIENT_NORMAL && !this.qtChannelObeject) {
            //浏览器里访问的本地模式，isClient=1
            VS_ShowAppPage();
          }
          this.preAddRemoteCanvas();
          this._addRemoteCanvas();
          //加载场景
          this._sceneComplete();
          setTimeout(function () {
            //告知三维加载场景
            // if(this.inParam.isShowLogin && !this.inParam.isRemoteRender) {
            //   this.Web_InitScene();
            // }
            this.Web_InitScene();
          }.bind(this),200);
        }else {
          this._doErrorCallback(code,msg);
        }
        console.log('InParam--', this.inParam);
        console.log("qtWebChannel--",GetQtController().qtChannelObeject);
      }.bind(this));
    }

    _scaleScreen() {
      if(this.inParam.clientType == CLIENT_NORMAL && this.inParam.isAutoScaleScreen) {
        let originWidth = document.documentElement.clientWidth;
        let originHeight = document.documentElement.clientHeight;
        let scaleX = originWidth*1.0 / this.inParam.clientWidth*1.0;
        let scaleY = originHeight*1.0 / this.inParam.clientHeight*1.0;
        document.body.style.transform = `scale(${scaleX},${scaleY})`;
        document.body.style.transformOrigin = 'left top';
      }
    }
}
